package com.example.gulimall.order;

import com.example.common.constant.BeanScanConstant;
import com.example.gulimall.order.config.GuLiMallBeanFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;







/**
 * 查看端口所在的进程：netstat -ano|findstr 9000 返回 PID
 * 根据进程号查看进程信息：tasklist|findstr PID
 *
 *
 * 本地事务失效的问题：
 *  同一个对象内事务方法互相调用默认失效，因为绕过了代理对象，事务使用代理对象来进行控制的
 * 解决方案：使用代理对象来调用事务方法
 *  1. 引入aop-starter
 *  （1）开启动态代理 @EnableAspectJAutoProxy(exposeProxy=true) (CGLIB) exposeProxy=true 对外暴露代理对象
 *  （2）AopContext.currentProxy(); 获取当前代理对象
 *  2. 直接从 spring 上下文中获取代理对象 (自定义组件需要实现 BeanFactory 接口)
 *   (1) ConfigurableApplicationContext run = SpringApplication.run(GulimallOrderApplication.class, args); 得到上下文
 *   (2) AutowireCapableBeanFactory beanFactory = run.getAutowireCapableBeanFactory(); 得到 bean 工厂
 *   (3) GuLiMallBeanFactory.setBean(beanFactory); 全局化 bean 工厂对象
 *   (4) GuLiMallBeanFactory.getBean(OrderService.class);
 *
 *
 *  spring cloud 整合 seata 0.8.0
 *  一、 Seata 服务端配置
 *  1. 下载 seata-server-0.8.0 https://github.com/seata/seata/releases/download/v0.8.1/seata-server-0.8.1.zip
 *  2. 下载好后修改配置文件
 *      2.1：registry.conf:
 *          ① registry/type = "nacos"
 *          ② registry/nacos/serverAddr = "localhost:8848"
 *      2.2: file.conf:
 *          这里一定一定要主意，my_seata_group 一定要与自己项目中配置项 spring.cloud.alibaba.seata.tx-service-group 相同，无论有多少个微服务，所有全部保持一致
 *          例如seata-server配置为：vgroup_mapping.my_seata_group = "default"， 那么项目中 spring.cloud.alibaba.seata.tx-service-group=my_seata_group
 *          ① service/vgroup_mapping.my_seata_group = "default
 *          ② store/mode = "db" 这里修改为 db，那么一定要修改自己得数据库信息，并且导入 global_table、branch_table、lock_table 三张表到数据库中
 *  二、各个微服务的配置：
 *      1. 修改 application.yml 文件
 *          增加配置项 spring.cloud.alibaba.seata.tx-service-group=my_seata_group  （my_seata_group与seata-server配置一致）
 *      2. 从 seata-server 中复制 file.conf 与 registry.conf 到各个微服务中
 *          这里建议最好是复制过来，因为这里有可能会出现 （NotSupportYetException: not support register type: null） 启动异常
 *      3. 新增加 seata 数据源的代理，这里可以参照 spring boot 数据源自动配置
 *          org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.Hikari
 *          #dataSource(org.springframework.boot.autoconfigure.jdbc.DataSourceProperties)
 *      4. （这一步可有可无），第三步的配置是可以公用的，将代理数据源放入 common 项目中，每个依赖代理数据源的微服务需要在
 *          #@SpringBootApplication(scanBasePackages={SEATA_PATH,SELF_PATH}) (SEATA_PATH:代理数据源包名,
 *          SELF_PATH:自己的包名，这里一定要添加自己的包名，否则不会扫描自己的配置)
 *
 */
@EnableRabbit
@EnableFeignClients
@EnableDiscoveryClient
@EnableRedisHttpSession
@SpringBootApplication(scanBasePackages = {
        BeanScanConstant.MP_PATH,
        BeanScanConstant.POLL_PATH,
        BeanScanConstant.ORDER_SELF,
        BeanScanConstant.FEIGN_PATH,
        BeanScanConstant.COMMON_PATH,
        BeanScanConstant.SENTINEL_PATH,
        BeanScanConstant.MQ_WEB_SERVICE,
        BeanScanConstant.RABBIT_ORDER_PATH,
        BeanScanConstant.RABBIT_COMMON_PATH
})
@MapperScan(basePackages= {
        BeanScanConstant.MQ_WEB_DAO,
        BeanScanConstant.ORDER_SELF_DAO
})
public class GulimallOrderApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(GulimallOrderApplication.class, args);
        AutowireCapableBeanFactory beanFactory = run.getAutowireCapableBeanFactory();
        GuLiMallBeanFactory.setBean(beanFactory);
    }

}


